package uaiContacts.controller;

import java.util.Locale;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import uaiContacts.model.Grupo;
import uaiContacts.service.GrupoService;
import uaiContacts.vo.GrupoListVO;

@Controller
@RequestMapping(value = "/protected/grupos")
public class GruposController {

	private static final String DEFAULT_PAGE_DISPLAYED_TO_USER = "0";

    @Autowired
    private GrupoService grupoService;

    @Autowired
    private MessageSource messageSource;

    @Value("10")
    private int maxResults;

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView welcome() {
        return new ModelAndView("gruposList");
    }
    
    @RequestMapping(method = RequestMethod.GET, produces = "application/json")
    public ResponseEntity<?> listAll(@RequestParam int page, Locale locale) {
        return createListAllResponse(page, locale);
    }
    
    @RequestMapping(method = RequestMethod.POST, produces = "application/json")
    public ResponseEntity<?> create(@ModelAttribute("grupo") Grupo grupo,
                                    @RequestParam(required = false) String searchFor,
                                    @RequestParam(required = false, defaultValue = DEFAULT_PAGE_DISPLAYED_TO_USER) int page,
                                    Locale locale) {
        grupoService.save(grupo);

        if (isSearchActivated(searchFor)) {
            return search(searchFor, page, locale, "message.create.success");
        }

        return createListAllResponse(page, locale, "message.create.success");
    }
    
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT, produces = "application/json")
    public ResponseEntity<?> update(@PathVariable("id") int grupoId,
                                    @RequestBody Grupo grupo,
                                    @RequestParam(required = false) String searchFor,
                                    @RequestParam(required = false, defaultValue = DEFAULT_PAGE_DISPLAYED_TO_USER) int page,
                                    Locale locale) {
        if (grupoId != grupo.getId()) {
            return new ResponseEntity<String>("Bad Request", HttpStatus.BAD_REQUEST);
        }

        grupoService.save(grupo);

        if (isSearchActivated(searchFor)) {
            return search(searchFor, page, locale, "message.update.success");
        }

        return createListAllResponse(page, locale, "message.update.success");
    }
    
    @RequestMapping(value = "/{grupoId}", method = RequestMethod.DELETE, produces = "application/json")
    public ResponseEntity<?> delete(@PathVariable("grupoId") int grupoId,
                                    @RequestParam(required = false) String searchFor,
                                    @RequestParam(required = false, defaultValue = DEFAULT_PAGE_DISPLAYED_TO_USER) int page,
                                    Locale locale) {


        try {
            grupoService.delete(grupoId);
        } catch (AccessDeniedException e) {
            return new ResponseEntity<Object>(HttpStatus.FORBIDDEN);
        }

        if (isSearchActivated(searchFor)) {
            return search(searchFor, page, locale, "message.delete.success");
        }

        return createListAllResponse(page, locale, "message.delete.success");
    }
    
    @RequestMapping(value = "/{name}", method = RequestMethod.GET, produces = "application/json")
    public ResponseEntity<?> search(@PathVariable("name") String name,
                                    @RequestParam(required = false, defaultValue = DEFAULT_PAGE_DISPLAYED_TO_USER) int page,
                                    Locale locale) {
        return search(name, page, locale, null);
    }
    
    private ResponseEntity<?> search(String nome, int page, Locale locale, String actionMessageKey) {
        GrupoListVO grupoListVO = grupoService.findByNomeLike(page, maxResults, nome);

        if (!StringUtils.isEmpty(actionMessageKey)) {
            addActionMessageToVO(grupoListVO, locale, actionMessageKey, null);
        }

        Object[] args = {nome};

        addSearchMessageToVO(grupoListVO, locale, "message.search.for.active", args);

        return new ResponseEntity<GrupoListVO>(grupoListVO, HttpStatus.OK);
    }
    
    private GrupoListVO listAll(int page) {
        return grupoService.findAll(page, maxResults);
    }

    private ResponseEntity<GrupoListVO> returnListToUser(GrupoListVO grupoList) {
        return new ResponseEntity<GrupoListVO>(grupoList, HttpStatus.OK);
    }

    private ResponseEntity<?> createListAllResponse(int page, Locale locale) {
        return createListAllResponse(page, locale, null);
    }

    private ResponseEntity<?> createListAllResponse(int page, Locale locale, String messageKey) {
    	GrupoListVO grupoListVO = listAll(page);

        addActionMessageToVO(grupoListVO, locale, messageKey, null);

        return returnListToUser(grupoListVO);
    }
    
    private GrupoListVO addActionMessageToVO(GrupoListVO grupoListVO, Locale locale, String actionMessageKey, Object[] args) {
        if (StringUtils.isEmpty(actionMessageKey)) {
            return grupoListVO;
        }

        grupoListVO.setActionMessage(messageSource.getMessage(actionMessageKey, args, null, locale));

        return grupoListVO;
    }

    private GrupoListVO addSearchMessageToVO(GrupoListVO grupoListVO, Locale locale, String actionMessageKey, Object[] args) {
        if (StringUtils.isEmpty(actionMessageKey)) {
            return grupoListVO;
        }

        grupoListVO.setSearchMessage(messageSource.getMessage(actionMessageKey, args, null, locale));

        return grupoListVO;
    }

    private boolean isSearchActivated(String searchFor) {
        return !StringUtils.isEmpty(searchFor);
    }
}
